package Hard;

// 1449.数位成本和为目标值的最大数字
/*
 * 最终的数位成本和必须恰好等于target
 * 换算为背包问题（拿了以后还可以再拿）
 * 数位1到9 对应9个物品，cost[0到8] 对应9个物品的重量；物品本身代表了自己的价值：
 *   要在尽可能的多拿物品（多拿数位），然后对结果进行排序，得到最大的价值
 *   所以可以把每个物品的价值都理解为1，因为每个物品的价值是等价的
 * dp[i]表示重量为i的时候，最大的数位和（String类型）
 * 对于每一个物品（数位），我们可以选择拿或者不拿，如果拿的话，则把它插入到头部，因为循环越往后，数位越大，这样就无需给已经获得的数位排序了
 *  每一个物品的重量（cost）为c，价值为1，因此数位和的长度直接代表了价值，无需在dp里存放价值
 *  每一个物品（数位）的值恰好为循环的次数k
 * 因此dp[i] = max(dp[i],"k"+dp[i-c]) 如果dp[i-c]为0（字符串里是""代表空），则"k"+dp[i-c]也为"" ，当二者长度相同时(这里是为了满足恰好等于target)
 * 如果二者长度不同，则dp[i] = 二者中长度长的那个
 * 不用避免过去的自己被先更新，且同一个数位可以重复使用多次，因此内部循环应该从小往大遍历
 * 最重要的一点：一个数字可以重复多次被拿，所以dp[i-c]应该循环数次，从小往大遍历可以直接解决这个问题
 * */
public class Solution1449 {
    public static String largestNumber(int[] cost, int target) {
        String[] dp = new String[target + 1];
        for (int i = 0; i < dp.length; i++) {
            dp[i]="";
        }
        // 固定cost的大小为9
        for (int a = 1; a <= 9; a++) {
            int c = cost[a - 1]; // 第a个数位的成本为cost[a-1]
            // 如果当前数位的成本大于target，就别考虑它了
            if(c > target){
                continue;
            }
            String k = "" + a; // 每一个物品（数位）的值恰好为循环的次数k
            // 每次应该先对当前物品，确定一下重量为多少的时候，可以拿它。
            if (dp[c].length() == 0) {
                dp[c] = k;
            }else if(dp[c].length() == 1){
                dp[c] = dp[c].compareTo(k)>0?dp[c]:k;
            }

            for (int i = c; i <= target; i++) {
                if (dp[i - c] == "") {
                    dp[i] = dp[i];
                } else {

                    if (dp[i].length() == (k + dp[i - c]).length()) {
                        // 比较字符串
                        if (dp[i].compareTo(k + dp[i - c]) < 0) {
                            dp[i] = k + dp[i - c];
                        }

                    } else if (dp[i].length() > (k + dp[i - c]).length()) {
                        dp[i] = dp[i];
                    } else {
                        dp[i] = k + dp[i - c];
                    }
                }
            }
        }
        if(dp[target]=="")
            return "0";
        return dp[target];
    }

    public static void main(String[] args) {
        System.out.println(largestNumber(new int[]{7,6,5,5,5,6,8,7,8},12));
    }
}
